package com.myopen.controller;

import com.alibaba.fastjson.JSON;
import com.jfinal.aop.Before;
import com.jfinal.core.ActionKey;
import com.jfinal.core.Controller;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.tx.Tx;
import com.jfinal.weixin.sdk.api.PaymentApi;
import com.jfinal.weixin.sdk.api.PaymentApi.TradeType;
import com.jfinal.weixin.sdk.kit.IpKit;
import com.jfinal.weixin.sdk.kit.PaymentKit;
import com.myopen.base.BaseVo;
import com.myopen.config.ConstConfig;
import com.myopen.kit.DeviceKit;
import com.myopen.kit.UUIDKit;
import com.myopen.model.Order;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

public class WeixinPayController extends Controller {
    //商户相关资料
    private static String appid = PropKit.get("weixin.appid");//微信公众号ID
    private static String partner = PropKit.get("weixin.pay.mchId");//微信支付商户号
    private static String paternerKey = PropKit.get("weixin.pay.key");//微信支付商户APIkey
    private static String notify_url = "http://"+PropKit.get("app.host")+"/wepay/notify";
    private static String return_url="http://"+PropKit.get("app.host")+"/paySuccess";

    @ActionKey("/wepay")
	public void wepay(){
        
		HttpServletRequest request=getRequest();
		if(DeviceKit.isWeChat(request)){
			forwardAction("/wepay/paccount");
		}else if(DeviceKit.isMobileDevice(request)){
			forwardAction("/wepay/wap");
		}else{
			forwardAction("/wepay/qrcode");
        }
        
    }
    
    private Map<String,String> createWepayInfo(HttpServletRequest request, String orderId,String trade_type){

		Record order=Order.dao.getRecordById(orderId);
		Double amount=order.getDouble("amount");

		String body="微信测试订单";
		String out_trade_no=order.getStr("number");
		String total_fee=((Double)(amount*100)).intValue()+""; //微信单位为分
		String spbill_create_ip=IpKit.getRealIpV2(request);
        String scene_info="";
        String openid="";
        String product_id="";

        System.out.println("spbill_create_ip:"+spbill_create_ip);

		if("MWEB".equals(trade_type)){
			Map<String,Object> scene_info_map=new HashMap<>();
			Map<String,Object> h5_info_map=new HashMap<>();
			h5_info_map.put("type", "");
			h5_info_map.put("wap_url", return_url);
			h5_info_map.put("wap_name", "维特鲁威");
			scene_info_map.put("h5_info", h5_info_map);
            scene_info=JSON.toJSONString(scene_info_map);
		}else if("JSAPI".equals(trade_type)){
            openid=(String)request.getSession().getAttribute(ConstConfig.WEIXIN_SESSION_OPEN_ID);
        }else if("NATIVE".equals(trade_type)){
            product_id=order.getStr("code");
        }

        Map<String,String> data=new HashMap<>();
        data.put("appid", appid);
        data.put("mch_id", partner);
		data.put("body", body);
		data.put("nonce_str", UUIDKit.getUUID());
		data.put("out_trade_no", out_trade_no);
		data.put("total_fee", total_fee);
		data.put("spbill_create_ip", spbill_create_ip);
		data.put("trade_type", trade_type);
		data.put("notify_url", notify_url);
		data.put("scene_info", scene_info);
		data.put("openid", openid);
		data.put("product_id", product_id);
        
		Order.dao.createPayHistory(orderId, out_trade_no, amount, ConstConfig.pay_wxpay, trade_type);

		return data;
	}

    /**
     * 公众号支付js-sdk
     */
    @Before(Tx.class)
    @ActionKey("/wepay/paccount")
    public void paccount() {

        String orderId=getPara("orderId");
		BaseVo baseVo=new BaseVo();
		baseVo.setCode("99");//默认失败

        HttpServletRequest request=getRequest();
        String trade_type=TradeType.JSAPI.name();

        Map<String, String> params = createWepayInfo(request,orderId,trade_type);

        String sign = PaymentKit.createSign(params, paternerKey);
        params.put("sign", sign);
        String xmlResult = PaymentApi.pushOrder(params);

        System.out.println(xmlResult+"===================");
        Map<String, String> result = PaymentKit.xmlToMap(xmlResult);

        String return_code = result.get("return_code");
        if (StrKit.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
            baseVo.setCode("99");//默认失败
            return;
        }
        String result_code = result.get("result_code");
        if (StrKit.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
            baseVo.setCode("99");//默认失败
            return;
        }
        // 以下字段在return_code 和result_code都为SUCCESS的时候有返回
        String prepay_id = result.get("prepay_id");

        Map<String, String> packageParams = new HashMap<String, String>();
        packageParams.put("appId", appid);
        packageParams.put("timeStamp", System.currentTimeMillis() / 1000 + "");
        packageParams.put("nonceStr", System.currentTimeMillis() + "");
        packageParams.put("package", "prepay_id=" + prepay_id);
        packageParams.put("signType", "MD5");
        String packageSign = PaymentKit.createSign(packageParams, paternerKey);
        packageParams.put("paySign", packageSign);

        baseVo.setCode("0");
        Record rdata=new Record();
        rdata.set("packageParams", packageParams);
        rdata.set("trade_type", trade_type);
        baseVo.setData(rdata);

        renderJson(baseVo);

        renderJson(baseVo);
    }

    /**
     * PC支付模式二，PC支付不需要openid
     */
    @Before(Tx.class)
	@ActionKey("/wepay/qrcode")
    public void wepay_qrcode() {

        String orderId=getPara("orderId");
		BaseVo baseVo=new BaseVo();
        baseVo.setCode("99");//默认失败

        HttpServletRequest request=getRequest();
        String trade_type=TradeType.NATIVE.name();

        Map<String, String> params = createWepayInfo(request,orderId,trade_type);
        String sign = PaymentKit.createSign(params, paternerKey);
        params.put("sign", sign);
        String xmlResult = PaymentApi.pushOrder(params);

        System.out.println(xmlResult+"===================");
        Map<String, String> result = PaymentKit.xmlToMap(xmlResult);

        String return_code = result.get("return_code");
        if (StrKit.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
            renderJson(baseVo);
            return;
        }
        String result_code = result.get("result_code");
        if (StrKit.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
            renderJson(baseVo);
            return;
        }
        
        // 以下字段在return_code 和result_code都为SUCCESS的时候有返回
        String prepay_id = result.get("prepay_id");
        // trade_type为NATIVE是有返回，可将该参数值生成二维码展示出来进行扫码支付
        String code_url = result.get("code_url");

        baseVo.setCode("0");
        Record rdata=new Record();
        rdata.set("code_url", code_url);
        rdata.set("trade_type", trade_type);
        baseVo.setData(rdata);

        renderJson(baseVo);

    }

    @Before(Tx.class)
	@ActionKey("/wepay/wap")
    public void wepay_wap() {
        String orderId=getPara("orderId");
		BaseVo baseVo=new BaseVo();
		baseVo.setCode("99");//默认失败

        HttpServletRequest request=getRequest();
        String trade_type=TradeType.MWEB.name();

        Map<String, String> params = createWepayInfo(request,orderId,trade_type);
        String sign = PaymentKit.createSign(params, paternerKey);
        params.put("sign", sign);
        String xmlResult = PaymentApi.pushOrder(params);

        System.out.println(xmlResult+"===================");
        Map<String, String> result = PaymentKit.xmlToMap(xmlResult);

        String return_code = result.get("return_code");
        if (StrKit.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
            renderJson(baseVo);
            return;
        }
        String result_code = result.get("result_code");
        if (StrKit.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
            renderJson(baseVo);
            return;
        }

        // 以下字段在return_code 和result_code都为SUCCESS的时候有返回

        String mweb_url=result.get("mweb_url");
        baseVo.setCode("0");
        Record rdata=new Record();
        rdata.set("mweb_url", mweb_url);
        rdata.set("trade_type", trade_type);
        baseVo.setData(rdata);

        renderJson(baseVo);
    }

    /**
     * 支付成功通知
     */
    @ActionKey("/wepay/notify")
	@Before(Tx.class)
    public void pay_notify() {
        // 支付结果通用通知文档: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
        String xmlMsg = HttpKit.readData(getRequest());
        System.out.println("支付通知="+xmlMsg);
        Map<String, String> params = PaymentKit.xmlToMap(xmlMsg);

        String result_code  = params.get("result_code");
        // 总金额
        String totalFee     = params.get("total_fee");
        // 商户订单号
        String out_trade_no      = params.get("out_trade_no");
        // 微信支付订单号
        String transaction_id      = params.get("transaction_id");
        // 支付完成时间，格式为yyyyMMddHHmmss
        String timeEnd      = params.get("time_end");

        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 避免已经成功、关闭、退款的订单被再次更新

        if(PaymentKit.verifyNotify(params, paternerKey)){
            if (("SUCCESS").equals(result_code)) {
                //更新订单信息

                Record payHistory=Order.dao.getPayHistory(out_trade_no);

                if("0".equals(payHistory.getStr("payStatus"))){
                    //待支付，可以支付
                    //微信支付只有交易成功的回调，交易完成的回调，可以放在订单完成的时候将支付状态改掉
                    Order.dao.successPayHistory(out_trade_no,transaction_id);//会同时修改订单状态
                    //Order.dao.completePayHistory(out_trade_no,transaction_id);//会同时修改订单状态
                }

                Map<String, String> xml = new HashMap<String, String>();
                xml.put("return_code", "SUCCESS");
                xml.put("return_msg", "OK");
                renderText(PaymentKit.toXml(xml));
                return;
            }
        }
        renderText("");
    }

    public Map<String,String> weixinpay_refund(String orderId,String path){

		Record orderPayHis=Order.dao.getPayHistorySuccessByOrderId(orderId);
        Record order=Order.dao.getRecordById(orderPayHis.getStr("orderId"));

        Double amount=order.getDouble("amount");

		String body=order.getStr("code");
		String out_trade_no=order.getStr("number");
		String total_fee=((Double)(amount*100)).intValue()+""; //微信单位为分

        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", appid);
        params.put("mch_id", partner);
        params.put("out_trade_no", orderPayHis.getStr("out_trade_no"));
        params.put("out_refund_no", System.currentTimeMillis() + "");
        params.put("total_fee", total_fee);
        params.put("refund_fee", total_fee);
        params.put("op_user_id", partner);
        String certPath = path+"/WEB-INF/weixin/cert/apiclient_cert.p12";
        
        // 申请退款，内部添加了随机字符串nonce_str和签名sign
        Map<String, String> resultMap = PaymentApi.refund(params, paternerKey, certPath);
        return resultMap;

    }

}
